package com.wiscamp.ninechapters.problems.domain.models.problems.answers;

import com.wiscamp.ninechapters.common.core.DateTimeHelper;
import com.wiscamp.ninechapters.common.core.ParseHelper;
import com.wiscamp.ninechapters.problems.enums.AnswerTypes;
import com.wiscamp.ninechapters.problems.math.SentenceUtils;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * 答案校验器
 */
public class AnswerValidator {

    private AnswerValidator() {
    }

    private static final Logger logger = LoggerFactory.getLogger(AnswerValidator.class);

    private static String formatSheetAnswer(String sheetAnswer) {
        return sheetAnswer.trim().toLowerCase();
    }

    public static boolean validateOption(@NotBlank long sheetOptionId, @NotBlank long correctAnswerOptionId) {
        return sheetOptionId == correctAnswerOptionId;
    }

    /**
     * 比较用户提交的答案和正确答案是否相同 - 数值型
     * 支持整数、小数、循环小数、分数、百分数、根数、科学计数法
     *
     * @param answerType
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateAnswerByType(@NotNull AnswerTypes answerType, @NotBlank String sheetAnswer, String correctAnswer) {

        if (correctAnswer.equalsIgnoreCase(""))
            throw new IllegalArgumentException("Invalid question answer.");

        var sameAnswer = false;
        switch (answerType) {
            case BOOLEAN:
                sameAnswer = validateBooleanAnswer(sheetAnswer, correctAnswer);
                break;
            case OPTION:
                long sheetOption = ParseHelper.parseLong(sheetAnswer);
                long correctOption = ParseHelper.parseLong(correctAnswer);
                sameAnswer = validateOptionAnswer(sheetOption, correctOption);
                break;
            case MULTIPLE_OPTION:
                sameAnswer = validateMultipleOptionAnswer(sheetAnswer, correctAnswer);
                break;
            case INTEGER:
            case DECIMAL:
            case RATE:
                sameAnswer = validateIntegerDecimalAnswer(sheetAnswer, correctAnswer);
                break;
            case FRACTION:
                sameAnswer = validateFractionAnswer(sheetAnswer, correctAnswer);
                break;
            case PERCENT:
                sameAnswer = validatePercentAnswer(sheetAnswer, correctAnswer);
                break;
            case RADICAL_NUMBER:
                sameAnswer = validateRadicalAnswer(sheetAnswer, correctAnswer);
                break;
            case LOOP_DECIMAL_NUMBER:
                sameAnswer = validateLoopDecimalAnswer(sheetAnswer, correctAnswer);
                break;
            case SCIENCE_NOTATION:
                sameAnswer = validateScienceNotationAnswer(sheetAnswer, correctAnswer);
                break;
            case INTEGER_RANGE:
            case RATIONAL_NUMBER_RANGE:
                sameAnswer = validateRangeAnswer(sheetAnswer, correctAnswer);
                break;
            case LATEX:
            case TEXT:
            case QUOTIENT_REMINDER:
            case GEOMETRY_ANGLE_DEGREE:
            case PROPORTION:
            case RATIO:
                sameAnswer = validateLatexAnswer(sheetAnswer, correctAnswer);
                break;
            case PLUS_MINUS_EXPRESSION:
            case TIMES_DIVISION_EXPRESSION:
            case ARITHMETIC_EXPRESSION:
                sameAnswer = validateExpressionAnswer(sheetAnswer, correctAnswer);
                break;
            case GEOMETRY_POINT_DENOTE:
            case GEOMETRY_XY_POINT_DENOTE:
            case GEOMETRY_XYZ_POINT_DENOTE:
            case GEOMETRY_VERTEX_DENOTE:
            case GEOMETRY_ANGLE_DENOTE:
            case GEOMETRY_EDGE_DENOTE:
            case GEOMETRY_TRIANGLE_DENOTE:
            case GEOMETRY_QUADRILATERAL_DENOTE:
            case GEOMETRY_PENTAGON_DENOTE:
                sameAnswer = validateGeometryDenoteAnswer(sheetAnswer, correctAnswer);
                break;
            case INTEGER_SERIES:
            case DECIMAL_SERIES:
                sameAnswer = validateIntegerSeriesAnswer(sheetAnswer, correctAnswer);
                break;
            case DECIMAL_SERIES_ASC:
            case DECIMAL_SERIES_DESC:
            case DECIMAL_SERIES_SORTED:
            case INTEGER_SERIES_ASC:
            case INTEGER_SERIES_DESC:
            case INTEGER_SERIES_SORTED:
                sameAnswer = validateSortedIntegerSeriesAnswer(sheetAnswer, correctAnswer);
                break;
            case DATE:
                sameAnswer = validateDateAnswer(sheetAnswer, correctAnswer);
                break;
            case TIME:
                sameAnswer = validateTimeAnswer(sheetAnswer, correctAnswer);
                break;
            case DATE_TIME:
                sameAnswer = validateDateTimeAnswer(sheetAnswer, correctAnswer);
                break;
            case COMPARE_OPERATOR:
            case ARITHMETIC_OPERATOR:
                sameAnswer = validateOperatorAnswer(sheetAnswer, correctAnswer);
                break;
            case MEASURE_UNIT_WEIGHT:
            case MEASURE_UNIT_AREA:
            case MEASURE_UNIT_CAPACITY:
            case MEASURE_UNIT_LENGTH:
            case MEASURE_UNIT_VOLUME:
            case MONEY_RMB:
                sameAnswer = validateMeasureUnitAnswer(sheetAnswer, correctAnswer);
                break;
            case GEOMETRY_ANGLE_EDGE_RELATION:
                sameAnswer = validateTextAnswer(sheetAnswer, correctAnswer);
                break;
            //case EQUATION_SOLUTION:
            //sameAnswer = validateEquationSolution(sheetAnswer, correctAnswer);
            //break;
            case INEQUALITY_SOLUTION:
                sameAnswer = validateInequalityAnswer(sheetAnswer, correctAnswer);
                break;
            case ARITHMETIC_EQUATION:
                sameAnswer = validateEquationAnswer(sheetAnswer, correctAnswer);
                break;
            default:
                logger.error("Can not find the matched method of a answer type. The answer type name is {}", answerType.getName());
        }

        if (sameAnswer == false)
            logger.info("validating the answer. The answer type is {} : {} / {} - {} :: {}", answerType.getValue(), answerType.toString() + " " + answerType.getName(), sheetAnswer, correctAnswer, sameAnswer);
        // logger.warn("校验答题卡答案时未匹配正确的答案类型: {} / {} - {} / {}", answerType.getValue(), answerType.getName(), sheetAnswer, correctAnswer);
        return sameAnswer;
    }

    /**
     * 校验有序整数数列答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateSortedIntegerSeriesAnswer(String sheetAnswer, String correctAnswer) {
        logger.debug("validating integer series answer.");
        var answer = formatSheetAnswer(sheetAnswer);
        return correctAnswer.equalsIgnoreCase(answer);
    }

    /**
     * 校验无序整数数列答案，与答案在数列中的顺序无关
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateIntegerSeriesAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        var sheetAnswerArray = answer.split(",");
        var correctAnswerArray = correctAnswer.split(",");
        if (sheetAnswerArray.length != correctAnswerArray.length) return false;
        for (var sheetNumber : sheetAnswerArray) {
            if (!correctAnswer.contains(sheetNumber))
                return false;
        }
        for (var correctNumber : correctAnswerArray) {
            if (!answer.contains(correctNumber))
                return false;
        }
        return true;
    }

    /**
     * 校验几何的表示
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateGeometryDenoteAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        return correctAnswer.equalsIgnoreCase(answer);
    }

    /**
     * 校验单选选项答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateOptionAnswer(long sheetAnswer, long correctAnswer) {
        return sheetAnswer == correctAnswer;
    }

    /**
     * 校验多选选项答案有一个选项不正确，则视为错误
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateMultipleOptionAnswer(String sheetAnswer, String correctAnswer) {
        var sheetOptions = ParseHelper.parseLong(sheetAnswer, ",");
        var correctOptions = ParseHelper.parseLong(correctAnswer, ",");
        if (sheetOptions.size() != correctOptions.size()) return false;
        for (var correctOption : correctOptions) {
            if (!sheetAnswer.contains(correctOption.toString()))
                return false;
        }
        return true;
    }

    /**
     * 校验范围答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateRangeAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        String[] numbers = answer.split("-");
        if (numbers.length != 2) return false;
        BigDecimal n1 = ParseHelper.parseBigDecimal(numbers[0]);
        BigDecimal n2 = ParseHelper.parseBigDecimal(numbers[1]);

        if (Objects.nonNull(n1) && Objects.nonNull(n2)) {
            String sheetAnswerText = answer.toLowerCase().replace(" ", "");
            String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
            return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
        } else
            return false;
    }

    /**
     * 校验科学计数法答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateScienceNotationAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!answer.contains("e") && !answer.contains("E")) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验循环小数
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    private static boolean validateLoopDecimalAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!answer.contains("\\dot")) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验通用Latex文本
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateLatexAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验表达式
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateExpressionAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return SentenceUtils.equalsExpression(sheetAnswerText, correctAnswerText);
    }

    /**
     * 校验计量单位
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateMeasureUnitAnswer(String sheetAnswer, String correctAnswer) {
        logger.debug("validating unit answer.");
        var answer = formatSheetAnswer(sheetAnswer);
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验日期答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateDateAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (Objects.isNull(DateTimeHelper.parseDate(answer))) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验时间答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateTimeAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (Objects.isNull(ParseHelper.parseTime(answer))) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验日期时间答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateDateTimeAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (Objects.isNull(DateTimeHelper.parseDateTime(answer))) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验比答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateRatioAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isRatio(answer)) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验比例答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateProportionAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isProportion(answer)) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验算术运算或比较操作符
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateOperatorAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isOperator(answer)) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验纯文本答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateTextAnswer(String sheetAnswer, String correctAnswer) {
        logger.debug("validating text answer.");
        var answer = formatSheetAnswer(sheetAnswer);
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验角度答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateAngleDegreeAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isAngleDegree(answer)) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验等式答案
     * TODO: 校验等式答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateEquationAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isEquation(answer)) return false;
        String userAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        //return correctAnswerText.equalsIgnoreCase(userAnswerText);
        return SentenceUtils.equalEquation(userAnswerText, correctAnswerText);
    }

    /**
     * 校验不等式答案
     * TODO: 校验不等式答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateInequalityAnswer(String sheetAnswer, String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!isInequality(answer)) return false;
        String userAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(userAnswerText);
    }

    /**
     * 是否不等式
     *
     * @param latexText
     * @return
     */
    public static boolean isExpression(String latexText) {
        return !latexText.contains("=")
                && !latexText.contains(">")
                && !latexText.contains("<")
                && !latexText.contains("\\lt")
                && !latexText.contains("\\gt")
                && !latexText.contains("\\le")
                && !latexText.contains("\\ge");
    }

    /**
     * 是否比
     *
     * @param latexText
     * @return
     */
    public static boolean isRatio(String latexText) {
        var patternText = "^-?[1-9]\\d*[:]{1}-?[1-9]\\d*";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否边
     *
     * @param latexText
     * @return
     */
    public static boolean isEdge(@NotBlank String latexText) {
        if (latexText.length() != 2) return false;
        var patternText = "[A-Z][A-Z]|[a-z][a-z]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否顶点
     *
     * @param latexText
     * @return
     */
    public static boolean isVertex(@NotBlank String latexText) {
        if (latexText.length() != 1) return false;
        var patternText = "[A-Z]|[a-z]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否三角形
     *
     * @param latexText
     * @return
     */
    public static boolean isTriangle(@NotBlank String latexText) {
        if (latexText.length() != 3) return false;
        var patternText = "[A-Z][A-Z][A-Z]|[a-z][a-z][a-z]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否四边形
     *
     * @param latexText
     * @return
     */
    public static boolean isQuadrilateral(@NotBlank String latexText) {
        if (latexText.length() != 4) return false;
        var patternText = "[A-Z][A-Z][A-Z][A-Z]|[a-z][a-z][a-z][a-z]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否五边形
     *
     * @param latexText
     * @return
     */
    public static boolean isPentagon(@NotBlank String latexText) {
        if (latexText.length() != 5) return false;
        var patternText = "[A-Z][A-Z][A-Z][A-Z][A-Z]|[a-z][a-z][a-z][a-z][a-z]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否角的表示
     *
     * @param latexText
     * @return
     */
    public static boolean isAngleDenote(@NotBlank String latexText) {
        if (latexText.length() != 3) return false;
        var patternText = "\\\\angle[{](\\d*|\\w*)[}]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否角度
     *
     * @param latexText
     * @return
     */
    public static boolean isAngleDegree(@NotBlank String latexText) {
        var patternText = "^[1-9]\\d*\\^\\\\circ$";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否算术运算或比较操作符
     *
     * @param latexText
     * @return
     */
    public static boolean isOperator(@NotBlank String latexText) {
        var patternText = "[+-×÷><=]";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        if (matcher.find()) return true;
        else {
            patternText = "\\\\lt|\\\\gt|\\\\le|\\\\ge";
            pattern = Pattern.compile(patternText);
            matcher = pattern.matcher(latexText);
            return matcher.find();
        }
    }

    /**
     * 是否时间文本
     *
     * @param latexText
     * @return
     */
    public static boolean isTime(@NotBlank String latexText) {
        var patternText = "^(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        if (matcher.find())
            return true;
        else {
            patternText = "^(20|21|22|23|[0-1]\\d):[0-5]\\d$";
            pattern = Pattern.compile(patternText);
            matcher = pattern.matcher(latexText);
            if (matcher.find())
                return true;
            else {
                patternText = "^(20|21|22|23|[0-1]\\d)$";
                pattern = Pattern.compile(patternText);
                matcher = pattern.matcher(latexText);
                return matcher.find();
            }
        }
    }

    /**
     * 是否日期时间文本
     *
     * @param latexText
     * @return
     */
    public static boolean isDateTime(@NotBlank String latexText) {
        if (!latexText.contains(" ")) return false;
        String[] array = latexText.split(" ");
        if (array.length != 2) return false;
        String date = array[0];
        String time = array[1];

        return isDate(date) && isTime(time);
    }

    /**
     * 是否日期文本
     *
     * @param latexText
     * @return
     */
    public static boolean isDate(@NotBlank String latexText) {
        var patternText = "^[1-9]\\d{3}-([1-9]|1[0-2])-([1-9]|[1-2][0-9]|3[0-1])$";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        if (matcher.find())
            return true;
        else {
            patternText = "^([1-9]|1[0-2])-([1-9]|[1-2][0-9]|3[0-1])$";
            pattern = Pattern.compile(patternText);
            matcher = pattern.matcher(latexText);
            return matcher.find();
        }
    }

    /**
     * 是否比例
     *
     * @param latexText
     * @return
     */
    public static boolean isProportion(@NotBlank String latexText) {
        var patternText = "^-?[1-9]\\d*[:]{1}-?[1-9]\\d*[=]{1}-?[1-9]\\d*[:]{1}-?[1-9]\\d*";
        var pattern = Pattern.compile(patternText);
        var matcher = pattern.matcher(latexText);
        return matcher.find();
    }

    /**
     * 是否等式
     *
     * @param latexText
     * @return
     */
    public static boolean isEquation(@NotBlank String latexText) {
        return latexText.contains("=");
    }

    /**
     * 是否不等式
     *
     * @param latexText
     * @return
     */
    public static boolean isInequality(@NotBlank String latexText) {
        return latexText.contains(">")
                || latexText.contains("<")
                || latexText.contains("\\lt")
                || latexText.contains("\\gt")
                || latexText.contains("\\le")
                || latexText.contains("\\ge");
    }

    /**
     * 校验整数或有限小数数值型用户答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateIntegerDecimalAnswer(@NotBlank String sheetAnswer, @NotBlank String correctAnswer) {
        String answer = formatSheetAnswer(sheetAnswer);
        // 用户答案为空串，答案错误
        if ("".equalsIgnoreCase(answer)) return false;

        if (correctAnswer.contains(".")) {
            // 按小数处理
            BigDecimal sheetDecimal = ParseHelper.parseBigDecimal(answer);
            BigDecimal correctDecimal = ParseHelper.parseBigDecimal(correctAnswer);
            if (Objects.isNull(sheetDecimal) || Objects.isNull(correctDecimal)) return false;
            return sheetDecimal.compareTo(correctDecimal) == 0;
        } else {
            // 按整数处理
            BigInteger sheetInteger = ParseHelper.parseBigInteger(answer);
            BigInteger correctInteger = ParseHelper.parseBigInteger(correctAnswer);
            if (Objects.isNull(sheetInteger) || Objects.isNull(correctInteger)) return false;
            return sheetInteger.compareTo(correctInteger) == 0;
        }
    }

    /**
     * 校验分数型用户答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateFractionAnswer(@NotBlank String sheetAnswer, @NotBlank String correctAnswer) {
        // 用户答案为空串，答案错误
        var sheetFraction = FractionUtils.toFraction(sheetAnswer);
        var correctFraction = FractionUtils.toFraction(correctAnswer);
        if (Objects.isNull(sheetFraction) || Objects.isNull(correctFraction)) return false;
        return FractionUtils.compareFraction(sheetFraction, correctFraction);
    }

    /**
     * 校验百分数答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validatePercentAnswer(@NotBlank String sheetAnswer, @NotBlank String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!answer.endsWith("%")) return false;

        String sheetAnswerText = answer.substring(0, answer.length() - 1);
        String correctAnswerText = correctAnswer.substring(0, correctAnswer.length() - 1);
        return validateIntegerDecimalAnswer(sheetAnswerText, correctAnswerText);
    }

    /**
     * 校验根数答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateRadicalAnswer(@NotBlank String sheetAnswer, @NotBlank String correctAnswer) {
        var answer = formatSheetAnswer(sheetAnswer);
        if (!answer.contains("\\sqrt")) return false;
        String sheetAnswerText = answer.toLowerCase().replace(" ", "");
        String correctAnswerText = correctAnswer.toLowerCase().replace(" ", "");
        return correctAnswerText.equalsIgnoreCase(sheetAnswerText);
    }

    /**
     * 校验布尔型用户答案
     *
     * @param sheetAnswer
     * @param correctAnswer
     * @return
     */
    public static boolean validateBooleanAnswer(@NotBlank String sheetAnswer, @NotBlank String correctAnswer) {
        return sheetAnswer.trim().equalsIgnoreCase(correctAnswer.trim());
    }


    /**
     * 获取文本对应数值类型
     * TODO: getFigureType 旧逻辑，需要废除
     * 整数-10，小数-20，分数=30，百分数=40, 根数=50
     *
     * @param text 根据答案文本内容判断答案类型
     * @return 类型编号枚举
     * @deprecated 使用answer type enum替代，即将废弃移除
     */
    @Deprecated(forRemoval = true)
    public static int getFigureType(@NotBlank String text) {
        var temp = text.trim();
        if (FractionUtils.toFraction(temp) != null)
            return 30;

        if (temp.contains("%"))
            return 40;

        if (temp.contains("\\sqrt"))
            return 50;

        if (temp.contains(".")) {
            try {
                Double.parseDouble(temp);
                return 20;
            } catch (NumberFormatException ex) {
                ex.printStackTrace();
            }
        } else {
            try {
                Long.parseLong(temp);
                return 10;
            } catch (NumberFormatException ex) {
                ex.printStackTrace();
            }
        }
        return 0;
    }
}


